package taskhandler

import (
	"encoding/csv"
	"encoding/json"
	"errors"
	"fmt"
	"io"
	"io/ioutil"
	"net/http"
	"os"
	"path"
	"path/filepath"
	"regexp"
	"strconv"
	"strings"
	"sync"
	"time"

	"cvevulner/common"
	"cvevulner/models"
	"cvevulner/util"

	"github.com/360EntSecGroup-Skylar/excelize/v2"
	"github.com/astaxie/beego"
	"github.com/astaxie/beego/logs"
)

const CVRFFKEY = "cvrfFileKey"
const BRANCHSKEY = "opBranchsKey"
const UNAFFECTCVRFKEY = "unaffectcvrfkey"
const FIXEDFLAGE = 1
const UNAFFECTFLAG = 2

var releaseDate map[string]int64

//CveExcel Excel export client
type CveExcel struct {
	ExcelName            string         //excel name
	ExcelHandel          *excelize.File //excel File handle
	CveSheetIdx          int            //CVE sheet index
	CveSheetName         string         // CVE sheet Name
	SecNoticeSheetIdx    int            //Security bulletin index
	SecNoticeSheetName   string         //Security bulletin sheet name
	SecNoticePrefix      string         //Security bulletin prefix
	SecNoticeSuffixIdx   int64          //Security bulletin suffix start value
	InfProductSheetName  string         //CVE Affected products
	InfProductSheetIndex int
	PackageURLSheetName  string
	PackageURLSheetIndex int
}

type IssueAndPkg struct {
	IssueMap map[int64]models.PullRequestIssue
	IssuePkg string
	Repo     string
	IssueId  int64
}

var fillLock sync.Mutex
var wgTrigger sync.WaitGroup

//GenerateCveExcel Generate Excel documents based on data.
//param snPrefix means security notice prefix.
//param snSuffix means security notice suffix append start value.
//param forceRewrite means whether to force the document to be rewritten.
func GenerateCveExcel(excelName, snPrefix string, snSuffix int64, forceRewrite bool) (err error) {
	//Query the data to be exported.
	count := models.GetCanExportVulnCenterCount()
	if count < 1 {
		return errors.New("No data to export! ")
	}
	//init excelClient
	ec := CveExcel{}
	err = ec.Init(excelName, snPrefix, snSuffix)
	if err != nil {
		return err
	}
	mode := ec.InitFileHandle(forceRewrite)
	if mode == 0 {
		ec.InitSheet()
		err = ec.FillHeader()
		if err != nil {
			logs.Error(err)
		}
	}
	ec.FillContent(count)
	//generate excel
	return ec.Save(mode)
}

//GenerateCveExcelByTrigger Generate cve&security notice excel file by trigger
func GenerateCveExcelByTrigger(affectBranch, excelName, snPrefix, startTime string, snSuffix int64,
	forceRewrite bool, pkgList []models.ExcelPackage, cvrfFileList map[string][]string,
	componentMap map[string]ComponentInfo, cvfrFileMap map[string]CvrfSa, cvexml *[]CveXml,
	dpdates *Updates, securityNotice map[string][]SecurityNoticeXml,
	packRpmx map[string][]PackRpm, cves []string) (err error) {
	if len(pkgList) == 0 {
		return errors.New("No data to export! ")
	}
	//init excelClient
	ec := CveExcel{}
	err = ec.Init(excelName, snPrefix, snSuffix)
	if err != nil {
		logs.Error("excelName: ", excelName, err)
		return err
	}
	mode := ec.InitFileHandle(forceRewrite)
	if mode == 0 {
		ec.InitSheet()
		err = ec.FillHeader()
		if err != nil {
			logs.Error(err)
		}
	}
	ec.FillContentTrigger(pkgList, startTime, affectBranch, cvrfFileList,
		componentMap, cvfrFileMap, cvexml, dpdates,
		securityNotice, packRpmx, cves)
	return ec.Save(mode)
}

//Init  init excel client
func (ec *CveExcel) Init(excelName, snPrefix string, snSuffix int64) (err error) {
	if excelName == "" || !(strings.HasSuffix(excelName, ".xlsx") || strings.HasSuffix(excelName, "xls")) {
		err = errors.New("excel name illegal")
		return
	}
	ec.ExcelName = excelName
	ec.SecNoticePrefix = snPrefix
	ec.SecNoticeSuffixIdx = snSuffix
	ec.CveSheetIdx = 0
	ec.CveSheetName = "CVE"
	ec.SecNoticeSheetIdx = 1
	ec.SecNoticeSheetName = "安全公告"
	ec.InfProductSheetIndex = 2
	ec.InfProductSheetName = "CVE影响的产品"
	ec.PackageURLSheetIndex = 3
	ec.PackageURLSheetName = "安全公告升级包链接"
	return nil
}

//InitFileHandle Initialize the file handle.
//param forceRewrite is true it means will create a new file otherwise it means append or new.
//the return value wm is 0 for new creation, and 1 for append.
func (ec *CveExcel) InitFileHandle(forceRewrite bool) (wm int8) {
	if forceRewrite {
		ec.ExcelHandel = excelize.NewFile()
		return 0
	}
	s, err := os.Stat(ec.ExcelName)
	if err != nil {
		ec.ExcelHandel = excelize.NewFile()
		return 0
	}
	if !s.IsDir() {
		file, err := excelize.OpenFile(ec.ExcelName)
		if err != nil {
			ec.ExcelHandel = excelize.NewFile()
			return 0
		}
		ec.ExcelHandel = file
		return 1

	}
	ec.ExcelHandel = excelize.NewFile()
	return 0

}

//InitSheet init excel sheet
func (ec *CveExcel) InitSheet() {
	ec.SecNoticeSheetIdx = ec.ExcelHandel.NewSheet(ec.SecNoticeSheetName)
	ec.InfProductSheetIndex = ec.ExcelHandel.NewSheet(ec.InfProductSheetName)
	ec.PackageURLSheetIndex = ec.ExcelHandel.NewSheet(ec.PackageURLSheetName)
	sn := ec.ExcelHandel.GetSheetName(ec.CveSheetIdx)
	ec.ExcelHandel.SetSheetName(sn, ec.CveSheetName)
}

//FillHeader fill the excel sheet header
func (ec *CveExcel) FillHeader() (err error) {
	err = ec.ExcelHandel.SetCellValue(ec.CveSheetName, "A1", "CVE编号")
	if err != nil {
		return
	}
	err = ec.ExcelHandel.MergeCell(ec.CveSheetName, "A1", "A2")
	if err != nil {
		return
	}
	err = ec.ExcelHandel.SetCellValue(ec.CveSheetName, "B1", "概要")
	if err != nil {
		return
	}
	err = ec.ExcelHandel.MergeCell(ec.CveSheetName, "B1", "B2")
	if err != nil {
		return
	}
	err = ec.ExcelHandel.SetCellValue(ec.CveSheetName, "C1", "Cvss Score")
	if err != nil {
		return
	}
	err = ec.ExcelHandel.MergeCell(ec.CveSheetName, "C1", "D1")
	if err != nil {
		return
	}
	err = ec.ExcelHandel.SetCellValue(ec.CveSheetName, "c2", "NVD")
	if err != nil {
		return
	}
	err = ec.ExcelHandel.SetCellValue(ec.CveSheetName, "D2", "OpenEuler")
	if err != nil {
		return
	}
	err = ec.ExcelHandel.SetCellValue(ec.CveSheetName, "E1", "Attack Vector")
	if err != nil {
		return
	}
	err = ec.ExcelHandel.MergeCell(ec.CveSheetName, "E1", "F1")
	if err != nil {
		return
	}
	err = ec.ExcelHandel.SetCellValue(ec.CveSheetName, "E2", "NVD")
	if err != nil {
		return
	}
	err = ec.ExcelHandel.SetCellValue(ec.CveSheetName, "F2", "OpenEuler")
	if err != nil {
		return
	}
	err = ec.ExcelHandel.SetCellValue(ec.CveSheetName, "G1", "Attack Complexity")
	if err != nil {
		return
	}
	err = ec.ExcelHandel.MergeCell(ec.CveSheetName, "G1", "H1")
	if err != nil {
		return
	}
	err = ec.ExcelHandel.SetCellValue(ec.CveSheetName, "G2", "NVD")
	if err != nil {
		return
	}
	err = ec.ExcelHandel.SetCellValue(ec.CveSheetName, "H2", "OpenEuler")
	if err != nil {
		return
	}
	err = ec.ExcelHandel.SetCellValue(ec.CveSheetName, "I1", "Privileges Required")
	if err != nil {
		return
	}
	err = ec.ExcelHandel.MergeCell(ec.CveSheetName, "I1", "J1")
	if err != nil {
		return
	}
	err = ec.ExcelHandel.SetCellValue(ec.CveSheetName, "I2", "NVD")
	if err != nil {
		return
	}
	err = ec.ExcelHandel.SetCellValue(ec.CveSheetName, "J2", "OpenEuler")
	if err != nil {
		return
	}
	err = ec.ExcelHandel.SetCellValue(ec.CveSheetName, "K1", "User Interaction")
	if err != nil {
		return
	}
	err = ec.ExcelHandel.MergeCell(ec.CveSheetName, "K1", "L1")
	if err != nil {
		return
	}
	err = ec.ExcelHandel.SetCellValue(ec.CveSheetName, "K2", "NVD")
	if err != nil {
		return
	}
	err = ec.ExcelHandel.SetCellValue(ec.CveSheetName, "L2", "OpenEuler")
	if err != nil {
		return
	}
	err = ec.ExcelHandel.SetCellValue(ec.CveSheetName, "M1", "Scope")
	if err != nil {
		return
	}
	err = ec.ExcelHandel.MergeCell(ec.CveSheetName, "M1", "N1")
	if err != nil {
		return
	}
	err = ec.ExcelHandel.SetCellValue(ec.CveSheetName, "M2", "NVD")
	if err != nil {
		return
	}
	err = ec.ExcelHandel.SetCellValue(ec.CveSheetName, "N2", "OpenEuler")
	if err != nil {
		return
	}

	err = ec.ExcelHandel.SetCellValue(ec.CveSheetName, "O1", "Confidentiality")
	if err != nil {
		return
	}
	err = ec.ExcelHandel.MergeCell(ec.CveSheetName, "O1", "P1")
	if err != nil {
		return
	}
	err = ec.ExcelHandel.SetCellValue(ec.CveSheetName, "O2", "NVD")
	if err != nil {
		return
	}
	err = ec.ExcelHandel.SetCellValue(ec.CveSheetName, "P2", "OpenEuler")
	if err != nil {
		return
	}
	err = ec.ExcelHandel.SetCellValue(ec.CveSheetName, "Q1", "Integrity")
	if err != nil {
		return
	}
	err = ec.ExcelHandel.MergeCell(ec.CveSheetName, "Q1", "R1")
	if err != nil {
		return
	}
	err = ec.ExcelHandel.SetCellValue(ec.CveSheetName, "Q2", "NVD")
	if err != nil {
		return
	}
	err = ec.ExcelHandel.SetCellValue(ec.CveSheetName, "R2", "OpenEuler")
	if err != nil {
		return
	}
	err = ec.ExcelHandel.SetCellValue(ec.CveSheetName, "S1", "Availability")
	if err != nil {
		return
	}
	err = ec.ExcelHandel.MergeCell(ec.CveSheetName, "S1", "T1")
	if err != nil {
		return
	}
	err = ec.ExcelHandel.SetCellValue(ec.CveSheetName, "S2", "NVD")
	if err != nil {
		return
	}
	err = ec.ExcelHandel.SetCellValue(ec.CveSheetName, "T2", "OpenEuler")
	if err != nil {
		return
	}
	err = ec.ExcelHandel.SetCellValue(ec.CveSheetName, "U1", "评分类型")
	if err != nil {
		return
	}
	err = ec.ExcelHandel.MergeCell(ec.CveSheetName, "U1", "U2")
	if err != nil {
		return
	}
	err = ec.ExcelHandel.SetCellValue(ec.CveSheetName, "V1", "安全公告")
	if err != nil {
		return
	}
	err = ec.ExcelHandel.MergeCell(ec.CveSheetName, "V1", "V2")
	if err != nil {
		return
	}
	err = ec.ExcelHandel.SetCellValue(ec.CveSheetName, "W1", "公告时间")
	if err != nil {
		return
	}
	err = ec.ExcelHandel.MergeCell(ec.CveSheetName, "W1", "W2")
	if err != nil {
		return
	}
	//Security bulletin header generation
	sh := []interface{}{"公告编号", "CVE编号", "简介", "概要", "主题", "描述", "影响组件", "影响产品", "影响包名", "参考", "公告时间"}
	err = ec.ExcelHandel.SetSheetRow(ec.SecNoticeSheetName, "A1", &sh)
	if err != nil {
		return err
	}
	ih := []interface{}{"CVE编号", "影响的产品", "包", "状态"}
	err = ec.ExcelHandel.SetSheetRow(ec.InfProductSheetName, "A1", &ih)
	if err != nil {
		return err
	}
	ph := []interface{}{"包名", "包下载链接"}
	err = ec.ExcelHandel.SetSheetRow(ec.PackageURLSheetName, "A1", &ph)
	if err != nil {
		return err
	}
	return nil
}

//FillContent fill the excel content
func (ec *CveExcel) FillContent(count int64) {
	pageSize := 50
	pageCount := count / int64(pageSize)
	if count%int64(pageSize) > 0 {
		pageCount++
	}
	for i := int64(0); i < pageCount; i++ {
		off := i * int64(pageSize)
		err := ec.handleWriteContent(off, pageSize)
		if err != nil {
			logs.Error(err)
		}
	}
}

func (ec *CveExcel) FillContentTrigger(pkgList []models.ExcelPackage, startTime,
	affectBranch string, cvrfFileList map[string][]string,
	componentMap map[string]ComponentInfo, cvfrFileMap map[string]CvrfSa, cvexml *[]CveXml,
	dpdates *Updates, securityNotice map[string][]SecurityNoticeXml,
	packRpmx map[string][]PackRpm, cves []string) {
	pl := len(pkgList)
	pageSize := 10
	pc := pl / 10
	if pl%10 > 0 {
		pc++
	}
	cd := make(chan []IssueAndPkg)
	start := 0
	end := 0
	for i := 0; i < pc; i++ {
		start = i * pageSize
		end = (i + 1) * pageSize
		if end > pl {
			end = pl
		}
		wgTrigger.Add(1)
		go getDateByGite(pkgList[start:end], startTime, cd, affectBranch, cves)
	}
	for i := 0; i < pc; i++ {
		wgTrigger.Add(1)
		go ec.handleGiteData(cd, affectBranch, cvexml, dpdates,
			securityNotice, packRpmx, cvrfFileList, componentMap, cvfrFileMap)
	}
	wgTrigger.Wait()
}

func FileExist(fileList []string) bool {
	if len(fileList) > 0 {
		for _, filex := range fileList {
			_, isErr := os.Stat(filex)
			if isErr != nil {
				return false
			}
		}
	}
	return true
}

func DelFile(fileList []string) {
	if len(fileList) > 0 {
		for _, filex := range fileList {
			err := os.Remove(filex)
			if err != nil {
				logs.Error(err)
			}
		}
	}
}

func (ec *CveExcel) handleWriteContent(off int64, size int) (err error) {
	list, err := models.GetCanExportCveData(off, size)
	if err != nil {
		return err
	}
	var cvrfFileList map[string][]string
	var componentMap map[string]ComponentInfo
	var cvfrFileMap map[string]CvrfSa
	lz := len(list)
	if lz > 0 {
		for _, v := range list {
			if v.Num == 1 {
				ec.setContentRow(v, "", cvrfFileList, componentMap, cvfrFileMap)
			} else if v.Num > 1 {
				//1.Obtain issue_tpl according to cve_num, if all issue_status == 2 0r issue_status == 6, then data can be exported
				list, err := models.GetIssueTplByCveNum(v.CveNum)
				if err != nil {
					logs.Error(err)
					continue
				}
				mergerList := make([]string, 0)
				canMerger := true
				for _, t := range list {
					if t.Status != 3 && t.Status != 4 {
						canMerger = false
						break
					}
					if t.IssueStatus == 2 {
						mergerList = append(mergerList, strconv.FormatInt(t.CveId, 10))
					}
				}
				//2.Find the corresponding ExcelExport data with the highest score from the template data of issue_status == 2
				if canMerger && len(mergerList) > 0 {
					canExport, err := models.GetCanExportCveDataSameNum(strings.Join(mergerList, ","))
					if err != nil {
						logs.Error(err)
					}
					ep := canExport[0]
					if len(canExport) > 1 {
						canExport = canExport[1:]
						for _, ex := range canExport {
							ep.Introduction = ep.Introduction + "\n" + ex.Introduction
							ep.Summary = ep.Summary + "\n" + ex.Summary
							ep.Theme = ep.Theme + "\n" + ex.Theme
							ep.Description = ep.Description + "\n" + ex.Description
							ep.OwnedComponent = ep.OwnedComponent + "\n" + ex.OwnedComponent
							ep.InfluenceComponent = ep.InfluenceComponent + "\n" + ex.InfluenceComponent
							ep.AffectProduct = ep.AffectProduct + "\n" + ex.AffectProduct
						}
					}
					ec.setContentRow(ep, "", cvrfFileList, componentMap, cvfrFileMap)
				}
			}
		}
	}
	return nil
}

func (ec *CveExcel) handleWriteContentSync(list []models.ExcelExport,
	affectBranch string, cvexml *[]CveXml, dpdates *Updates,
	securityNotice map[string][]SecurityNoticeXml,
	packRpmx map[string][]PackRpm, cvrfFileList map[string][]string,
	componentMap map[string]ComponentInfo, cvfrFileMap map[string]CvrfSa) (err error) {
	lz := len(list)
	if lz > 0 {
		for _, v := range list {
			if v.OrganizateId == 2 {
				logs.Error("opengauss, data: ", v)
				continue
			}
			affectBool := affectBrachRep(&v, affectBranch)
			if !affectBool {
				logs.Error("Unaffected version, data: ", v)
				continue
			}
			fillLock.Lock()
			ec.setContentRow(v, affectBranch, cvrfFileList, componentMap, cvfrFileMap)
			fillLock.Unlock()
			fillLock.Lock()
			BuildXml(cvexml, &v, securityNotice, packRpmx, affectBranch)
			fillLock.Unlock()
			if v.Num == 1 {
				// The current data num==1 will not be processed
				//fillLock.Lock()
				//BuildXml(cvexml, &v, securityNotice, packRpmx)
				//fillLock.Unlock()
				logs.Info("Num:1, info: ", v)
			} else if v.Num > 1 {
				logs.Info("Num: ", v.Num, ", info: ", v)
				//Handling CVE_NUM duplicates
				//1.Obtain issue_tpl according to cve_num, if all issue_status == 2 0r issue_status == 6, then data can be exported
				list, err := models.GetIssueTplByCveNum(v.CveNum)
				if err != nil {
					logs.Error("GetIssueTplByCveNum, err: ", err)
					continue
				}
				mergerList := make([]string, 0)
				canMerger := true
				for _, t := range list {
					if t.Status != 3 && t.Status != 4 {
						canMerger = false
						break
					}
					if t.IssueStatus == 2 {
						mergerList = append(mergerList, strconv.FormatInt(t.CveId, 10))
					}
				}
				if canMerger && len(mergerList) > 0 {
					canExport, err := models.GetCanExportCveDataSameNum(strings.Join(mergerList, ","))
					if err != nil {
						logs.Error("GetCanExportCveDataSameNum, err: ", err)
					}
					// Fill in the content of the xml file
					canExport1 := make([]models.ExcelExport, len(canExport))
					copy(canExport1, canExport)
					//addXmlData(canExport1, cvexml, affectBranch, securityNotice, packRpmx)
					// Fill in the content of the excel file
					ep := canExport[0]
					ep.SecID = v.SecID
					//affectBrachRep(&ep, affectBranch)
					if ep.AffectProduct != "" && len(ep.AffectProduct) > 1 {
						if ep.AffectProduct != affectBranch {
							ep.Introduction = strings.ReplaceAll(ep.Introduction, ep.AffectProduct, affectBranch)
							ep.Theme = strings.ReplaceAll(ep.Theme, ep.AffectProduct, affectBranch)
							ep.AffectProduct = affectBranch
						}
					}
					if len(canExport) > 1 {
						canExport = canExport[1:]
						m := make(map[string]struct{})
						m[ep.OwnedComponent] = struct{}{}
						for _, ex := range canExport {
							affectBool := affectBrachRep(&ex, affectBranch)
							if !affectBool {
								logs.Error("Unaffected version, data: ", ex)
								continue
							}
							//component repeat do not append
							if _, ok := m[ex.OwnedComponent]; !ok {
								ep.Introduction = ep.Introduction + "\n" + ex.Introduction
								ep.Summary = ep.Summary + "\n" + ex.Summary
								ep.Theme = ep.Theme + "\n" + ex.Theme
								ep.Description = ep.Description + "\n" + ex.Description
								ep.InfluenceComponent = ep.InfluenceComponent + "\n" + ex.InfluenceComponent
								ep.AffectProduct = ep.AffectProduct + "\n" + ex.AffectProduct
								ep.OwnedComponent = ep.OwnedComponent + "\n" + ex.OwnedComponent
								m[ex.OwnedComponent] = struct{}{}
							}
						}
					}
				}
			}
		}
	}
	return nil
}

func affectBrachRep(xmlp *models.ExcelExport, affectBranch string) bool {
	affectBool := false
	if xmlp.AffectProduct != "" && len(xmlp.AffectProduct) > 1 {
		if xmlp.AffectProduct != affectBranch {
			affectBranchsxList := strings.Split(xmlp.AffectProduct, "/")
			for _, ab := range affectBranchsxList {
				if ab == affectBranch {
					affectBool = true
					xmlp.Introduction = strings.ReplaceAll(xmlp.Introduction, xmlp.AffectProduct, affectBranch)
					xmlp.Theme = strings.ReplaceAll(xmlp.Theme, xmlp.AffectProduct, affectBranch)
					xmlp.AffectProduct = affectBranch
					break
				}
			}
		} else {
			affectBool = true
		}
	}
	return affectBool
}

func FindUnaffectBrach(xmlp *models.ExcelExport, affectBranch, accessToken, owner string) bool {
	branchArry, _ := GetBranchesInfo(accessToken, owner, xmlp.OwnedComponent, 1)
	affectBool := false
	if xmlp.AffectedVersion != "" && len(xmlp.AffectedVersion) > 1 {
		affSlice := strings.Split(xmlp.AffectedVersion, ",")
		if len(affSlice) > 0 {
			for _, aff := range affSlice {
				aff = common.BranchVersionRep(aff)
				if strings.Contains(aff, affectBranch+":") || strings.Contains(aff, affectBranch+"：") {
					branchSlice := []string{}
					if strings.Contains(aff, ":") {
						branchSlice = strings.Split(aff, ":")
					} else if strings.Contains(aff, "：") {
						branchSlice = strings.Split(aff, "：")
					}
					if len(branchSlice) == 2 {
						if strings.TrimSpace(branchSlice[0]) == affectBranch &&
							len(strings.TrimSpace(branchSlice[1])) > 1 &&
							strings.TrimSpace(branchSlice[1]) != "受影响" {
							// Query branch information
							for _, arr := range branchArry {
								if arr == strings.TrimSpace(branchSlice[0]) {
									affectBool = true
									break
								}
							}
						}
					}
				}
			}
		}
	}
	return affectBool
}

func addXmlData(canExport []models.ExcelExport, cvexml *[]CveXml, affectBranch string,
	securityNotice map[string][]SecurityNoticeXml, packRpmx map[string][]PackRpm) {
	for _, xmlp := range canExport {
		affectBool := affectBrachRep(&xmlp, affectBranch)
		if !affectBool {
			logs.Error("Unaffected version, data: ", xmlp)
			continue
		}
		fillLock.Lock()
		BuildXml(cvexml, &xmlp, securityNotice, packRpmx, affectBranch)
		fillLock.Unlock()
	}
}

func UpdateUseOpenEulerSaNum() {
	useOpenEulerNum := beego.AppConfig.String("xml::use_openeuler_num")
	if len(useOpenEulerNum) > 1 {
		useOpenEulerNumSlice := strings.Split(useOpenEulerNum, ",")
		for _, use := range useOpenEulerNumSlice {
			var sax models.SaNumber
			sax.OpenEulerSANum = use
			sax.Status = 1
			models.GetSaNumber(&sax, "OpenEulerSANum", "Status")
			if sax.SaId > 0 {
				sax.Status = 2
				sax.UpdateTime = common.GetCurTime()
				models.UpdateSaNumber(&sax, "status")
			}
			var saFile models.SaFileList
			saFile.FileName = "cvrf-" + use + ".xml"
			models.GetCvrfFileName(&saFile, "FileName")
			if saFile.FileId == 0 {
				saFile.Status = 1
				saFile.CreateTime = common.GetCurTime()
				models.InsertCvrfFileName(&saFile)
			}
		}
	}
}

func GetOpenEulerSaNum() string {
	var sa models.SaNumber
	curYears := strconv.Itoa(time.Now().Year())
	models.GetSaNumberByYears(&sa, curYears, 1, 1)
	if sa.SaId > 0 {
		sa.Status = 2
		sa.UpdateTime = common.GetCurTime()
		models.UpdateSaNumber(&sa, "status")
	}
	return sa.OpenEulerSANum
}

func StoreComponentInfo(componentMap map[string]ComponentInfo,
	v models.ExcelExport, affectBranch string) bool {
	repFlag := false
	influenceComponent := ""
	fileDir := beego.AppConfig.String("fileDir")
	common.CreateDir(fileDir)
	if len(v.InfluenceComponent) > 1 {
		influenceComponent = v.InfluenceComponent
	} else {
		influenceComponent = v.OwnedComponent
	}
	packNameStruct, pOk := componentMap[influenceComponent]
	if !pOk || len(packNameStruct.OpenEulerSANum) < 3 {
		var coponentInfo ComponentInfo
		openEulerSANum := GetOpenEulerSaNum()
		if openEulerSANum == "" {
			openEulerSANum = v.OpenEulerSANum
		}
		coponentInfo.OpenEulerSANum = openEulerSANum
		coponentInfo.CvrfFileName = filepath.Join(fileDir, "cvrf-"+openEulerSANum+".xml")
		coponentInfo.OwnedComponent = influenceComponent
		coponentInfo.UpdateFlag = 2
		openEulerScoreSlice := make([]float64, 0)
		openEulerScoreSlice = append(openEulerScoreSlice, v.OpenEulerScore)
		coponentInfo.OpenEulerScore = openEulerScoreSlice
		cveNumSlice := make([]string, 0)
		cveNumSlice = append(cveNumSlice, v.CveNum)
		branchCve := make(map[string]BrachCveInfo)
		var brachCveInfo BrachCveInfo
		openEulerSANum1 := GetOpenEulerSaNum()
		if openEulerSANum1 == "" {
			openEulerSANum1 = v.OpenEulerSANum
		}
		brachCveInfo.OpenEulerSANum = openEulerSANum1
		brachCveInfo.CvrfFileName = filepath.Join(fileDir, "cvrf-"+openEulerSANum1+".xml")
		brachCveInfo.CveNumSlice = cveNumSlice
		brachCveInfo.OpenEulerScore = openEulerScoreSlice
		branchCve[affectBranch] = brachCveInfo
		coponentInfo.CveNumMap = branchCve
		coponentInfo.CveNum = cveNumSlice
		componentMap[influenceComponent] = coponentInfo
	} else {
		packNameStruct.UpdateFlag = 2
		repFlagX := false
		if len(packNameStruct.CveNum) > 0 {
			for _, cveX := range packNameStruct.CveNum {
				if cveX == v.CveNum {
					repFlagX = true
					break
				}
			}
			if !repFlagX {
				packNameStruct.CveNum = append(packNameStruct.CveNum, v.CveNum)
				packNameStruct.OpenEulerScore = append(packNameStruct.OpenEulerScore, v.OpenEulerScore)
			}
		} else {
			cveNumSlice := make([]string, 0)
			cveNumSlice = append(cveNumSlice, v.CveNum)
			packNameStruct.CveNum = cveNumSlice
			openEulerScoreSlice := make([]float64, 0)
			openEulerScoreSlice = append(openEulerScoreSlice, v.OpenEulerScore)
			packNameStruct.OpenEulerScore = openEulerScoreSlice
		}
		if len(packNameStruct.CveNumMap) > 0 {
			if branchCvex, brOk := packNameStruct.CveNumMap[affectBranch]; !brOk {
				cveNumSlice := make([]string, 0)
				cveNumSlice = append(cveNumSlice, v.CveNum)
				openEulerScoreSlice := make([]float64, 0)
				openEulerScoreSlice = append(openEulerScoreSlice, v.OpenEulerScore)
				var brachCveInfo BrachCveInfo
				openEulerSANum1 := GetOpenEulerSaNum()
				if openEulerSANum1 == "" {
					openEulerSANum1 = v.OpenEulerSANum
				}
				brachCveInfo.OpenEulerSANum = openEulerSANum1
				brachCveInfo.CvrfFileName = filepath.Join(fileDir, "cvrf-"+openEulerSANum1+".xml")
				brachCveInfo.CveNumSlice = cveNumSlice
				brachCveInfo.OpenEulerScore = openEulerScoreSlice
				packNameStruct.CveNumMap[affectBranch] = brachCveInfo
			} else {
				for _, cve := range branchCvex.CveNumSlice {
					if cve == v.CveNum {
						repFlag = true
						break
					}
				}
				if !repFlag {
					branchCvex.CveNumSlice = append(branchCvex.CveNumSlice, v.CveNum)
					branchCvex.OpenEulerScore = append(branchCvex.OpenEulerScore, v.OpenEulerScore)
					packNameStruct.CveNumMap[affectBranch] = branchCvex
				}
			}
		} else {
			branchCve := make(map[string]BrachCveInfo)
			cveNumSlice := make([]string, 0)
			cveNumSlice = append(cveNumSlice, v.CveNum)
			openEulerScoreSlice := make([]float64, 0)
			openEulerScoreSlice = append(openEulerScoreSlice, v.OpenEulerScore)
			var brachCveInfo BrachCveInfo
			openEulerSANum1 := GetOpenEulerSaNum()
			if openEulerSANum1 == "" {
				openEulerSANum1 = v.OpenEulerSANum
			}
			brachCveInfo.OpenEulerSANum = openEulerSANum1
			brachCveInfo.CvrfFileName = filepath.Join(fileDir, "cvrf-"+openEulerSANum1+".xml")
			brachCveInfo.CveNumSlice = cveNumSlice
			brachCveInfo.OpenEulerScore = openEulerScoreSlice
			branchCve[affectBranch] = brachCveInfo
			packNameStruct.CveNumMap = branchCve
		}
		componentMap[influenceComponent] = packNameStruct
	}
	return repFlag
}

func SaveCvrfName(cvrfFileList map[string][]string, cvrffileName, mapKey string) {
	cvrfFileSlice, cvrfOk := cvrfFileList[mapKey]
	if cvrfOk {
		fileExist := false
		for _, cvrfVuale := range cvrfFileSlice {
			if cvrfVuale == cvrffileName {
				fileExist = true
			}
		}
		if !fileExist {
			cvrfFileSlice = append(cvrfFileSlice, cvrffileName)
			cvrfFileList[mapKey] = cvrfFileSlice
		}
	} else {
		cvrfNameSlice := make([]string, 0)
		cvrfNameSlice = append(cvrfNameSlice, cvrffileName)
		cvrfFileList[mapKey] = cvrfNameSlice
	}
}

func BranchCvrfData(v models.ExcelExport,
	affectBranch, cvrffileName string, cvrfFileList map[string][]string,
	componentMap map[string]ComponentInfo,
	cvfrFileMap map[string]CvrfSa, pkg []models.Package, branchFlag int) {
	branchCvrfSaStruct, bCvrfSaOk := cvfrFileMap[cvrffileName]
	if !bCvrfSaOk {
		// Query whether there is data in the database
		var cfr models.CvrfSaRecord
		var cvrfsa CvrfSa
		if branchFlag == 1 {
			cfr.OpenEulerSANum = componentMap[v.InfluenceComponent].OpenEulerSANum
		} else {
			cfr.OpenEulerSANum = componentMap[v.InfluenceComponent].CveNumMap[affectBranch].OpenEulerSANum
		}
		tbErr := models.GetCvrfRecord(&cfr, "openeuler_sa_num")
		if tbErr == nil && cfr.Id > 0 {
			// Download data from file server
			// Read file content
			readErr := ReadCvrfXml(cvrffileName, &cvrfsa)
			if readErr != nil {
				cvrfsa = CvrfSa{}
			} else {
				var componentInfo ComponentInfo
				componentInfo = componentMap[v.InfluenceComponent]
				componentInfo.UpdateFlag = 1
				componentMap[v.InfluenceComponent] = componentInfo
			}
		}
		BuildCvrfXml(&cvrfsa, v, affectBranch, cvrfFileList, componentMap, pkg, branchFlag)
		cvfrFileMap[cvrffileName] = cvrfsa
	} else {
		BuildCvrfXml(&branchCvrfSaStruct, v, affectBranch, cvrfFileList, componentMap, pkg, branchFlag)
		cvfrFileMap[cvrffileName] = branchCvrfSaStruct
	}
	SaveCvrfName(cvrfFileList, cvrffileName, CVRFFKEY)
}

func procCvrfData(v models.ExcelExport,
	affectBranch string, cvrfFileList map[string][]string,
	componentMap map[string]ComponentInfo,
	cvfrFileMap map[string]CvrfSa, pkg []models.Package) {
	totalCvrffileName := componentMap[v.InfluenceComponent].CvrfFileName
	branchCvrffileName := componentMap[v.InfluenceComponent].CveNumMap[affectBranch].CvrfFileName
	BranchCvrfData(v, affectBranch, branchCvrffileName, cvrfFileList, componentMap, cvfrFileMap, pkg, 2)
	BranchCvrfData(v, affectBranch, totalCvrffileName, cvrfFileList, componentMap, cvfrFileMap, pkg, 1)
}

func (ec *CveExcel) setContentRow(v models.ExcelExport,
	affectBranch string, cvrfFileList map[string][]string,
	componentMap map[string]ComponentInfo, cvfrFileMap map[string]CvrfSa) {
	pkg, pkgErr := models.GetCvePackageList(v.SecID, affectBranch)
	if pkgErr != nil {
		logs.Error(pkgErr)
	}
	if v.PublicDate == "" {
		v.PublicDate = time.Now().Format("2006-01-02")
	}
	pkgStr := getPkgStr(pkg)
	repFlag := StoreComponentInfo(componentMap, v, affectBranch)
	if !repFlag {
		procCvrfData(v, affectBranch, cvrfFileList, componentMap, cvfrFileMap, pkg)
		sn := []interface{}{v.OpenEulerSANum, v.CveNum, v.Introduction, v.Summary,
			v.Theme, v.Description, v.InfluenceComponent,
			v.AffectProduct, pkgStr, v.ReferenceLink, v.PublicDate}
		axis, searched := ec.searchValueInSheet(ec.SecNoticeSheetName, v.InfluenceComponent)
		if !searched {
			fillErr := ec.fillSecurityNoticeSheet(sn)
			if fillErr != nil {
				logs.Error(fillErr)
			}
		} else {
			//merge openEuler SA notice data
			colReg := regexp.MustCompile(`[A-Z]*`)
			col := colReg.FindString(axis)
			row := strings.Trim(axis, col)
			rCN := "B" + row
			rRl := "J" + row
			vcn, _ := ec.ExcelHandel.GetCellValue(ec.SecNoticeSheetName, rCN)
			vcn += ";\n" + v.CveNum
			_ = ec.ExcelHandel.SetCellValue(ec.SecNoticeSheetName, rCN, vcn)
			vrl, _ := ec.ExcelHandel.GetCellValue(ec.SecNoticeSheetName, rRl)
			vrl += "\n" + v.ReferenceLink
			_ = ec.ExcelHandel.SetCellValue(ec.SecNoticeSheetName, rRl, vrl)
			rSAN := fmt.Sprintf("A%s", row)
			vSAN, cellError := ec.ExcelHandel.GetCellValue(ec.SecNoticeSheetName, rSAN)
			if cellError == nil {
				v.OpenEulerSANum = vSAN
			}
			//merger description
			rd := "F" + row
			vd, _ := ec.ExcelHandel.GetCellValue(ec.SecNoticeSheetName, rd)
			dSplit := strings.Split(v.Description, "Security Fix(es):")
			if len(dSplit) > 1 {
				if !strings.Contains(vd, dSplit[0]) {
					vd = dSplit[0] + vd
				}
				vd += dSplit[1]
			}
			_ = ec.ExcelHandel.SetCellValue(ec.SecNoticeSheetName, rd, vd)
			//Get the highest-rated theme
			rd = "E" + row
			theme, err := models.GetCanExportTheme(vcn, v.OwnedComponent, affectBranch)
			if err == nil && len(theme) > 1 {
				_ = ec.ExcelHandel.SetCellValue(ec.SecNoticeSheetName, rd, theme)
			}
		}
		cve := []interface{}{v.CveNum, v.CveBrief, v.NVDScore, v.OpenEulerScore, v.NattackVector, v.OattackVector,
			v.NattackComplexity, v.OattackComplexity, v.NprivilegeRequired, v.OprivilegeRequired, v.NuserInteraction,
			v.OuserInteraction, v.Nscope, v.Oscope, v.Nconfidentiality, v.Oconfidentiality, v.Nintegrity, v.Ointegrity,
			v.Navailability, v.Oavailability, v.ScoreType, v.OpenEulerSANum, v.PublicDate}
		shErr := ec.fillCveSheetRow(cve)
		if shErr != nil {
			logs.Error(shErr)
		}
		ap := []interface{}{v.CveNum, v.AffectProduct, v.InfluenceComponent, v.AffectStatus}
		err := ec.fillAffectProductSheet(ap)
		if err != nil {
			logs.Error(err)
		}
		for _, v := range pkg {
			pk := []interface{}{v.PackName, v.PackUrl}
			if _, ok := ec.searchValueInSheet(ec.PackageURLSheetName, v.PackName); !ok {
				err := ec.fillPackageSheet(pk)
				if err != nil {
					logs.Error(err)
				}
			}
		}
	}
}

func getPkgStr(pkg []models.Package) string {
	pkgStr := ""
	if len(pkg) == 0 {
		return pkgStr
	}
	var ps []string
	for _, v := range pkg {
		if v.PackName != "" {
			ps = append(ps, v.PackName)
		}
	}
	return strings.Join(ps, ";\n")
}

func (ec *CveExcel) searchValueInSheet(sheetName, value string) (axis string, searched bool) {
	if value == "" {
		return
	}
	sheet, err := ec.ExcelHandel.SearchSheet(sheetName, value)
	if err != nil {
		return
	}
	if len(sheet) > 0 {
		for _, k := range sheet {
			cellValue, _ := ec.ExcelHandel.GetCellValue(sheetName, k)
			if cellValue == value {
				searched = true
				axis = k
				break
			}
		}
		return
	}
	return
}

func (ec *CveExcel) fillCveSheetRow(row []interface{}) (err error) {
	rows, err := ec.ExcelHandel.GetRows(ec.CveSheetName)
	if err != nil {
		return err
	}
	idx := len(rows) + 1
	axis := fmt.Sprintf("A%d", idx)
	err = ec.ExcelHandel.SetSheetRow(ec.CveSheetName, axis, &row)
	return err
}

func (ec *CveExcel) fillSecurityNoticeSheet(row []interface{}) (err error) {
	rows, err := ec.ExcelHandel.GetRows(ec.SecNoticeSheetName)
	if err != nil {
		return err
	}
	idx := len(rows) + 1
	axis := fmt.Sprintf("A%d", idx)
	err = ec.ExcelHandel.SetSheetRow(ec.SecNoticeSheetName, axis, &row)
	return err
}

func (ec *CveExcel) fillAffectProductSheet(row []interface{}) (err error) {
	rows, err := ec.ExcelHandel.GetRows(ec.InfProductSheetName)
	if err != nil {
		return err
	}
	idx := len(rows) + 1
	axis := fmt.Sprintf("A%d", idx)
	err = ec.ExcelHandel.SetSheetRow(ec.InfProductSheetName, axis, &row)
	return err
}

func (ec *CveExcel) fillPackageSheet(row []interface{}) (err error) {
	rows, err := ec.ExcelHandel.GetRows(ec.PackageURLSheetName)
	if err != nil {
		return err
	}
	idx := len(rows) + 1
	axis := fmt.Sprintf("A%d", idx)
	err = ec.ExcelHandel.SetSheetRow(ec.PackageURLSheetName, axis, &row)
	return err
}

//Save save the excel content to file
func (ec *CveExcel) Save(md int8) error {
	if md == 0 {
		return ec.ExcelHandel.SaveAs(ec.ExcelName)
	}
	return ec.ExcelHandel.Save()

}

//ExtractPackageData extract the package data by csv file
func ExtractPackageData(lp string) (pkgList []models.ExcelPackage, err error) {
	pkgLock.Lock()
	defer pkgLock.Unlock()
	if lp == "" || path.Ext(lp) != ".CSV" {
		return pkgList, errors.New("the file path is error")
	}
	file, err := os.Open(lp)
	if err != nil {
		return pkgList, err
	}
	defer file.Close()
	reader := csv.NewReader(file)
	for {
		line, err := reader.Read()
		if err == io.EOF {
			break
		} else if err != nil {
			return pkgList, err
		}
		if len(line) >= 3 && len(line[0]) > 3 {
			pkgList = append(pkgList, models.ExcelPackage{PubTime: line[0], Repo: line[1], Packages: line[2]})
		}
	}
	return
}

func getDataUnaffect(startTime string, cves []string) ([]models.IssueTemplate, error) {
	issueTemp, err := models.GetUnffectIssueNumber(startTime, cves)
	if err != nil || issueTemp == nil {
		logs.Info("No unaffected data needs to be processed, startTime: ", startTime)
		return issueTemp, err
	}
	return issueTemp, err
}

func getDateByGite(pkgList []models.ExcelPackage, startTime string, c chan<- []IssueAndPkg, affectBranch string, cves []string) {
	defer wgTrigger.Done()
	token := beego.AppConfig.String("gitee::git_token")
	//token := "8457c66db66955376519059b97e33dd1"
	owner := beego.AppConfig.String("gitee::owner")
	// Time difference in different time zones
	saTimeStampZone, ok := beego.AppConfig.Int64("excel::sa_timestamp_zone")
	if ok != nil {
		saTimeStampZone = 3600 * 8
	}
	st := util.TimeStrToInt(startTime, "2006-01-02")
	if len(cves) != 0 {
		st = 0
	}
	chData := make([]IssueAndPkg, 0)
	for _, v := range pkgList {
		//logs.Info("excel, v===>", v)
		rt := util.TimeStrToInt(v.PubTime, "20060102 15-04-05") + saTimeStampZone
		// Query the current issues that need to be dealt with
		issueTemp, err := models.GetIssueNumber(v.Repo, cves)
		if err != nil || issueTemp == nil {
			logs.Info("No need to deal with ", v.Repo)
			continue
		}
		for _, isTemp := range issueTemp {
			if len(cves) != 0 && !filterDataInSlice(isTemp.CveNum, cves) {
				continue
			}
			//logs.Info("isTemp===>", isTemp)
			prList := getRepoIssueAllPR(affectBranch, token, owner, v.Repo, st, rt, isTemp)
			//get pull request related issue
			repoIssue := make(map[int64]models.PullRequestIssue, 0)
			for _, p := range prList {
				//getPRRelatedAllIssue(token, owner, v.Repo, st, rt, p.Number, repoIssue)
				repoIssue[p.Id] = p
			}
			if len(repoIssue) > 0 {
				chData = append(chData, IssueAndPkg{IssueMap: repoIssue, IssuePkg: v.Packages,
					Repo: v.Repo, IssueId: isTemp.IssueId})
			}
		}
	}
	c <- chData
}

func (ec *CveExcel) handleGiteData(c <-chan []IssueAndPkg, affectBranch string, cvexml *[]CveXml,
	dpdates *Updates, securityNotice map[string][]SecurityNoticeXml,
	packRpmx map[string][]PackRpm, cvrfFileList map[string][]string,
	componentMap map[string]ComponentInfo, cvfrFileMap map[string]CvrfSa) {
	defer wgTrigger.Done()
	data := <-c
	var pkgList []string
	for _, v := range data {
		//parse package string to list
		pkgList = strings.Split(v.IssuePkg, " ")
		if len(pkgList) == 0 {
			logs.Error("Data is filtered, v.IssuePkg: ", v.IssuePkg)
			continue
		}
		affectIssueProc(v, affectBranch, cvexml, dpdates, securityNotice, packRpmx,
			cvrfFileList, componentMap, cvfrFileMap, pkgList, ec)
	}
}

func UnaffectIssueProc(affectBranch string, cvrfFileList map[string][]string,
	componentMap map[string]ComponentInfo, startTime, accessToken, owner string,
	unaffectcvrf *UnaffectCvrfSa, unaffectYear int, cves []string) {
	data, err := getDataUnaffect(startTime, cves)
	if len(data) > 0 {
		for _, v := range data {
			issueExist, _ := GetCveSecurityNotice(v.CveNum, v.Repo, true)
			if issueExist {
				if productExist, _ := GetCveProduct(v.CveNum, v.Repo); productExist {
					var center models.VulnCenter
					center.CveId = v.CveId
					centErr := models.GetVulnCenterByCid(&center, "cve_id")
					if centErr == nil {
						center.IsExport = 1
						models.UpdateVulnCenter(&center, "is_export")
					}
					continue
				}
				if ok, _ := GetCveProduct(v.CveNum, v.Repo, affectBranch); ok {
					continue
				}
			}
			if len(cves) != 0 && !filterDataInSlice(v.CveNum, cves) {
				continue
			}
			//save data to excel
			el, err := models.GetCanExportExcelData(v.CveNum, v.IssueNum, v.OwnedComponent, v.IssueId)
			if err != nil {
				logs.Error("GetCanExportExcelData, err: ", err, "tpl.CveNum, tpl.IssueNum: ", v.CveNum, v.IssueNum, v.OwnedComponent)
				continue
			}
			for _, vx := range el {
				if filterFixBranch(&vx, vx.CveNum, affectBranch) {
					continue
				}
				affectBool := FindUnaffectBrach(&vx, affectBranch, accessToken, owner)
				if affectBool {
					logs.Info("Unaffected version, data: ", vx.CveNum, vx.OwnedComponent, vx.AffectProduct)
					cveNumList := strings.Split(vx.CveNum, "-")
					if cveNumList != nil && len(cveNumList) > 1 {
						cveYears, yearErr := strconv.Atoi(cveNumList[1])
						if yearErr == nil {
							if cveYears <= unaffectYear {
								logs.Error("The unaffected version year is no longer "+
									"processed in the scope, cveYears: ", cveYears, ",unaffectYear: ", unaffectYear)
								continue
							}
						}
					}
					// Generate unaffected cvrf files
					fillLock.Lock()
					BuildUnaffectVulnerabilitySet(unaffectcvrf, vx, affectBranch, componentMap)
					fillLock.Unlock()
				}
			}
		}
	} else {
		logs.Error(err)
	}
}

//filter existing data
func filterDataInSlice(data string, filterList []string) bool {
	for _, v := range filterList {
		if strings.EqualFold(data, v) {
			return true
		}
	}
	return false
}

// if cve exist affected and label exist CVE/FIXED return true
func filterFixBranch(data *models.ExcelExport, cve, branch string) (has bool) {
	has = false
	if !strings.Contains(data.IssueLabel, "CVE/FIXED") {
		return
	}
	if data.AffectedVersion != "" && len(data.AffectedVersion) > 1 {
		versions := strings.Split(data.AffectedVersion, ",")
		for _, v := range versions {
			var branchSlice []string
			if strings.Contains(v, ":") {
				branchSlice = strings.Split(v, ":")
			} else if strings.Contains(v, "：") {
				branchSlice = strings.Split(v, "：")
			}
			if len(branchSlice) == 2 && len(branchSlice[1]) != 0 {
				if strings.EqualFold(branchSlice[0], branch) && branchSlice[1] == "受影响" {
					has = true
					break
				}
			}
		}
	}
	return
}

func affectIssueProc(v IssueAndPkg, affectBranch string, cvexml *[]CveXml,
	dpdates *Updates, securityNotice map[string][]SecurityNoticeXml,
	packRpmx map[string][]PackRpm, cvrfFileList map[string][]string,
	componentMap map[string]ComponentInfo, cvfrFileMap map[string]CvrfSa,
	pkgList []string, ec *CveExcel) {
	for _, iv := range v.IssueMap {
		tpl := models.IssueTemplate{IssueNum: iv.Number, Repo: iv.Repo, IssueId: v.IssueId}
		err := models.GetIssueTemplateByColName(&tpl, "issue_num", "repo", "issue_id")
		if err != nil {
			logs.Error("GetIssueTemplateByColName, ----", err, iv.Number, iv.Repo, v.IssueId)
			continue
		}
		//save data to excel
		el, err := models.GetCanExportExcelData(tpl.CveNum, tpl.IssueNum, tpl.OwnedComponent, tpl.IssueId)
		if err != nil {
			logs.Error("GetCanExportExcelData, err: ", err, "tpl.CveNum, tpl.IssueNum: ",
				tpl.CveNum, tpl.IssueNum, tpl.OwnedComponent)
			continue
		}
		// Check whether the cve data has been released sa
		issueExist, _ := GetCveSecurityNotice(tpl.CveNum, tpl.Repo, true)
		if issueExist {
			if productExist, _ := GetCveProduct(tpl.CveNum, tpl.Repo); productExist {
				var center models.VulnCenter
				center.CveId = tpl.CveId
				centErr := models.GetVulnCenterByCid(&center, "cve_id")
				if centErr == nil {
					center.IsExport = 1
					models.UpdateVulnCenter(&center, "is_export")
				}
				continue
			}
			if ok, _ := GetCveProduct(tpl.CveNum, v.Repo, affectBranch); ok {
				continue
			}
		}

		// Branches that have been fixed before the release no longer publish announcements
		if releaseTimeOfVersion, ok := releaseDate[affectBranch]; ok {
			if iv.MergeAt < releaseTimeOfVersion {
				tpl.IsIgnore = 1
				models.UpdateIssueTemplate(&tpl, "is_ignore")
				continue
			}
		}

		err = models.ReplacePackageByCveId(pkgList, tpl.CveId, affectBranch)
		if err != nil {
			logs.Error("ReplacePackageByCveId, err: ", err, "tpl.CveId: ", tpl.CveId)
			continue
		}
		err = ec.handleWriteContentSync(el, affectBranch, cvexml, dpdates,
			securityNotice, packRpmx, cvrfFileList, componentMap, cvfrFileMap)
		if err != nil {
			logs.Error("handleWriteContentSync, err: ", err)
		}
	}
}

func getRepoIssueAllPR(affectBranch, token, owner, repo string, startTime,
	releaseTime int64, isTemp models.IssueTemplate) (prList []models.PullRequestIssue) {
	url := fmt.Sprintf("https://gitee.com/api/v5/repos/%v/issues/%v/pull_requests", owner, isTemp.IssueNum)
	req, err := http.NewRequest(http.MethodGet, url, nil)
	if err != nil {
		logs.Error("NewRequest, url: ", url, ",err: ", err)
		return
	}
	q := req.URL.Query()
	q.Add("access_token", token)
	q.Add("repo", repo)
	req.URL.RawQuery = q.Encode()
	resp, err := http.DefaultClient.Do(req)
	if err != nil {
		logs.Error("DefaultClient, url: ", url, ",err: ", err)
		return
	}
	if resp.StatusCode == http.StatusOK {
		issuePr := make([]map[string]interface{}, 0)
		read, err := ioutil.ReadAll(resp.Body)
		if err != nil {
			logs.Error("ReadAll, url: ", url, ",err: ", err)
			return
		}
		resp.Body.Close()
		err = json.Unmarshal(read, &issuePr)
		if err != nil {
			logs.Error("Unmarshal, url: ", url, ",err: ", err)
			return
		}
		for _, v := range issuePr {
			if _, ok := v["id"]; !ok {
				continue
			}
			pr := models.PullRequestIssue{}
			if v["state"].(string) == "merged" && v["mergeable"].(bool) {
				//mt := v["closed_at"].(string).(time.Time).Local().Unix()
				closedAt := v["closed_at"].(string)
				mt := util.TimeStrToInt(closedAt[:19], "2006-01-02T15:04:05")
				mergedAt := v["merged_at"].(string)
				ct := util.TimeStrToInt(mergedAt[:19], "2006-01-02T15:04:05")
				//logs.Info("======>>mt: ", mt, ", startTime: ", startTime, ",releaseTime: ", releaseTime, ":ct:", ct, ",repo:", repo, ", pr: ", v)
				//ct := v["merged_at"].(string).(time.Time).Local().Unix()
				var pt int64
				if mt > 0 && ct > 0 {
					if mt > ct {
						pt = ct
					} else {
						pt = mt
					}

					if pt >= startTime && pt <= releaseTime {
						if v["base"].(map[string]interface{})["label"].(string) == affectBranch {
							pr.Id = int64(v["id"].(float64))
							pr.Number = isTemp.IssueNum
							pr.CveNumber = isTemp.CveNum
							pr.Repo = repo
							pr.BrFlag = true
							pr.Branch = affectBranch
							pr.MergeAt = pt
							prList = append(prList, pr)
						}
					}
				}
			}
		}
	} else {
		resp.Body.Close()
	}
	return
}

func InitReleaseDate() {
	releaseDate = make(map[string]int64)
	releaseDateConfig := beego.AppConfig.DefaultString("excel::release_date_of_version", "")
	for _, v := range strings.Split(strings.Trim(releaseDateConfig, ";"), ";") {
		split := strings.Split(v, ":")
		releaseDate[split[0]] = util.TimeStrToInt(split[1], "2006-01-02") + 3600*24
	}
}
